package org.rainwalk.bill.api.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.rainwalk.bill.api.model.Response;
import org.rainwalk.bill.api.model.ResponseCode;
import org.rainwalk.bill.api.model.SessionUser;
import org.rainwalk.bill.entity.AppUser;
import org.rainwalk.bill.entity.Token;
import org.rainwalk.bill.model.enums.AppUserAuthorizedEnum;
import org.rainwalk.bill.service.IAppUserService;
import org.rainwalk.bill.service.ITokenService;
import org.rainwalk.bill.util.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 身份认证与权限拦截
 *
 * @author chenyuheng create class on 2021-01-21
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class AuthInterceptor implements HandlerInterceptor {

    @Value("${const.token.header}")
    private String tokenName;

    @Value("${const.token.ttl}")
    private int tokenTtl;

    private final ITokenService tokenService;

    private final IAppUserService userService;

    public static final String USER_SESSION = "sessionUser";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //放行登陆接口
        String method = request.getMethod();
        String uri = request.getRequestURI();
        if ("POST".equals(method) && uri.startsWith("/bill/token")) {
            return true;
        }

        String tokenString = request.getHeader(tokenName);
        if (StrUtil.isBlank(tokenString)) {
            writeJson(response, Response.fail(ResponseCode.UNAUTHORIZED));
            return false;
        }
        //校验token正确性
        Token token = tokenService.getById(tokenString);
        if (token == null || (TimeUtil.getNow() - token.getRefreshTime() > tokenTtl)) {
            writeJson(response, Response.fail(ResponseCode.UNAUTHORIZED));
            return false;
        }
        //刷新token时间
        tokenService.refresh(token.getId());

        //校验用户
        AppUser appUser = userService.getById(token.getUserId());
        if (appUser == null) {
            writeJson(response, Response.fail(ResponseCode.UNAUTHORIZED));
            return false;
        } else if (! AppUserAuthorizedEnum.AUTHORIZED.getValue().equals(appUser.getAuthorized())) {
            writeJson(response, Response.fail(ResponseCode.INSUFFICIENT_PERMISSIONS));
            return false;
        }

        // 添加用户到session
        request.getSession().setAttribute(USER_SESSION, new SessionUser(appUser));
        return true;
    }

    private void writeJson(HttpServletResponse httpResponse, Response response) {
        httpResponse.setHeader("Content-Type", "application/json;charset=utf-8");
        httpResponse.setStatus(HttpServletResponse.SC_OK);
        try (PrintWriter writer = httpResponse.getWriter()) {
            writer.write(JSONUtil.toJsonStr(response));
            writer.flush();
        } catch (IOException e) {
            log.warn("响应请求失败，响应结果：{}", response);
        }
    }


}
